#include "pika_hal.h"
#include "PikaVM.h"

#include "sht3x_driver.h"

// SHT3X device address
#define SHT3X_SLAVE_ADDRESS 0x44

#define SHT3X_SDA "P21"
#define SHT3X_SCL "P22"

pika_dev* sht3x_iic;

uint8_t cal_crc8(uint8_t* buf, size_t len) {
    uint8_t crc = 0xff;  // initialization
    while (len-- > 0) {
        crc ^= *buf++;
        for (int i = 0; i < 8; ++i) {
            crc = (crc & 0x80) ? (crc << 1) ^ 0x31  // polynominal
                               : (crc << 1);
        }
    }
    pika_debug("crc:%02x", crc);
    return crc;
}


bool check_crc(uint8_t* buf) {
    return (cal_crc8(buf, 2) == buf[2] && cal_crc8(buf + 3, 2) == buf[5]);
}

int sht3x_init(void) {
    // Open the I2C device
    sht3x_iic = pika_hal_open(PIKA_HAL_SOFT_IIC, "soft_iic");

    pika_hal_SOFT_IIC_config iic_cfg = {0};
    // Configure the IIC device
    iic_cfg.slave_addr = SHT3X_SLAVE_ADDRESS;
    iic_cfg.SCL = pika_hal_open(PIKA_HAL_GPIO, SHT3X_SCL);
    iic_cfg.SDA = pika_hal_open(PIKA_HAL_GPIO, SHT3X_SDA);

    pika_hal_ioctl(sht3x_iic, PIKA_HAL_IOCTL_CONFIG, &iic_cfg);
    pika_hal_ioctl(sht3x_iic, PIKA_HAL_IOCTL_ENABLE);

    pika_sleep_ms(100);
    return 0; // Success
}

// Function to read data from AHT20
int sht3x_read(SHT3X_Data* data) {

    // Send measurement command to SHT3X
    uint8_t measure_cmd[2] = {0x2C, 0x06};
    if (pika_hal_write(sht3x_iic, &measure_cmd, 2) != 2) {
        return -1; // Error
    }
    // Read the measurement results
    uint8_t rawData[6] = {0};
    pika_sleep_ms(100);
    if (pika_hal_read(sht3x_iic, &rawData, 6) != 6) {
        return -1; // Error
    }

    if (!check_crc(rawData)) {
	    return -1; // crc error
    }
      
    pika_debug("aht20 raw:[0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X]", rawData[0], rawData[1], rawData[2], rawData[3], rawData[4], rawData[5]);

    // Parse the raw data into the structure
    // This depends on the data format specified in the SHT3X datasheet
    // You may need to adjust this parsing according to the actual data format
    data->humidity = ((rawData[3] << 8) | rawData[4]) * 100.0 / 65535.0;
    data->temperature = ((rawData[0] << 8) | rawData[1]) * 175.0 / 65535.0 - 45.0;

    pika_debug("aht20 data: status: 0x%02X, temperature: %f, humidity: %f", data->status, data->temperature, data->humidity);
    return 0; // Success
}
